package com.webtest.mvctest2.controller;

import com.webtest.mvctest2.dao.CriteriaCustomer;
import com.webtest.mvctest2.dao.CustomerDao;
import com.webtest.mvctest2.dao.factory.CustomerDaoFactory;
import com.webtest.mvctest2.model.Customer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Comparator;
import java.util.List;

/**
 * @author lzy
 * @version v1.0
 * Create DateTime: 2018/7/27 21:07
 */
public class CustomerServlet extends HttpServlet {
    private static final long serialVersionUID = -2935170895824223616L;
    private static final Logger LOGGER = LoggerFactory.getLogger(CustomerServlet.class);
    private CustomerDao customerDao = CustomerDaoFactory.getInstance().getCustomerDAO();

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doPost(req, resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 1. 获取servletPath：:/addCustomer.do或/query.do等
        String servletPath = req.getServletPath();
        // 2. 去掉/和.do，得到类似于edit或addCustomer这样的字符串
        String[] paths = servletPath.split("/");
        String methodName = paths[paths.length - 1];
        methodName = methodName.substring(0, methodName.length() - 3).trim();
        try {
            // 3. 利用烦着获取methodName对应的方法
            Method method = getClass().getDeclaredMethod(methodName, HttpServletRequest.class, HttpServletResponse.class);
            // 4. 利用反射调用对应的方法
            method.invoke(this, req, resp);
        } catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) {
            LOGGER.error("invoke error in doPost", e);
        }
    }

    private void query(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String name = req.getParameter("name");
        String address = req.getParameter("address");
        String phone = req.getParameter("phone");

        LOGGER.info("query method");
        // 1. 调用CustmoerDAO的getAll得到Customer集合
        CriteriaCustomer criteriaCustomer = new CriteriaCustomer(name, address, phone);
        List<Customer> customers = customerDao.getForListWithCriteriaCustomer(criteriaCustomer);
        customers.sort(Comparator.comparingInt(Customer::getId));
        // 2. 把Customer集合翻入request中
        req.setAttribute("customers", customers);
        // 3. 转发页面到index.jsp（不能使用重定向）
        req.getRequestDispatcher("/customer2/index.jsp").forward(req, resp);
    }

    private void addCustomer(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        LOGGER.info("add method");
        //1.获取表单参数:name, address, phone
        String name = req.getParameter("name");
        String address = req.getParameter("address");
        String phone = req.getParameter("phone");

        //2.检测name是否已经被占用
        //2.1 调用CustomerDAO的getCountWithName(String name)获取name在数据库中是否存在
        long count = customerDao.getCountWithName(name);

        //2.2 如果名称已经存在，则相应newcustomer.jsp页面：
        // 通过请求转发的方式相应newcustomer.jsp
        if (count > 0) {
            ///2.2.1 要求在newcustomer.jsp页面显示一个错误消息：用户名name已经被占用，请重新选择
            // 在request中放入一个message：用户名name已经被占用，请重新选择，在页面上通过request.getAttribute()的方式来显示
            req.setAttribute("message", "用户名" + name + "已经被占用，请重新选择");
            //2.2.2 newcustomer的表单可以回显
            // 通过value="<%=request.getParameter("name")==null?"":request.getParameter("name")%>"的方式进行回显
            // 2.2.3结束方法 return
            req.getRequestDispatcher("/customer2/newcustomer.jsp").forward(req, resp);
            return;
        }
        //3.若验证通过， 则继续执行后续操作。把表单参数封装为一个Customer对象
        Customer customer = new Customer(name, address, phone);
        //4.调用dao的save（）方法执行保存操作
        customerDao.save(customer);
        // 5.重定向到success.jsp页面，使用重定向可以避免出现表单的重复提交问题
        resp.sendRedirect(req.getContextPath() + "/customer2/success.jsp");
//        req.getRequestDispatcher("/customer/success.jsp").forward(req, resp);
    }

    private void deleteCustomer(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        LOGGER.info("delete method");
        String idStr = req.getParameter("id");
        int id = 0;
        // try...catch的作用：防止idStr不能转为int
        // 若不能转则id=0，无法进行任何删除操作
        try {
            id = Integer.parseInt(idStr);
            customerDao.delete(id);
        } catch (Exception e) {
            LOGGER.error("delete customer", e);
        }
        resp.sendRedirect(req.getContextPath() + "/query.do");
    }

    private void updateCustomer(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        LOGGER.info("update method");
        //1.获取表单参数:id, name, address, phone,oldName
        String name = req.getParameter("name");
        String address = req.getParameter("address");
        String phone = req.getParameter("phone");
        String oldName = req.getParameter("oldName");
        String strId = req.getParameter("id");

        //2.检测name是否已经被占用
        //2.1 比较name和oldName是否相同，若不相同说明name可用
        //2.2 若不相同，则调用CustomerDAO中的getCountWithName（）获取name在数据库中是否存在
        if (!oldName.equalsIgnoreCase(name)) {
            long count = customerDao.getCountWithName(name);
            if (count > 0) {
                //2.3 若返回值大于0，则响应updatecustomer.jsp页面：在页面显示一个错误消息：用户名name已经被占用，请重新选择
                //2.3.1 在updatecustomer.jsp页面显示一个错误消息：用户名name已经被占用，请重新选择
                //在request中放入一个属性message：用户名name已经被占用，请重新选择
                //在页面通过request.getAttribute(message)的方式来显示
                req.setAttribute("message", "用户名" + name + "已经被占用！请重新选择");
                //2.3.2 updatecustomer.jsp的表单可以回显
                // 通过value="<%=request.getParameter("name")==null?"":request.getParameter("name")%>"的方式进行回显，address，phone显示提交的信纸，而name显示oldNme，而不是新提交的name
                // 2.2.3结束方法 return
                req.getRequestDispatcher("/customer2/updatecustomer.jsp").forward(req, resp);
                return;
            }
        }

        //3.若验证通过， 则继续执行后续操作。把表单参数封装为一个Customer对象
        Customer customer = new Customer(name, address, phone);
        customer.setId(Integer.parseInt(strId));
        //4.调用dao的update（）方法执行更新操作
        customerDao.update(customer);
        // 5.重定向到query.do，使用重定向可以避免出现表单的重复提交问题
        resp.sendRedirect(req.getContextPath() + "/query.do");
    }

    private void editCustomer(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        LOGGER.info("deit method");

        String forwardPath = "/customer2/customernotfound.jsp";
        //1.获取请求参数id
        String idStr = req.getParameter("id");
        boolean isNumber = idStr.matches("^[0-9]*$");

        if (isNumber) {
            //2.调用CustomerDAO的customerDAO.get(id)获取和id对应的Customer对象
            try {
                int id = Integer.parseInt(idStr);
                Customer customer = customerDao.get(id);
                if (customer != null) {
                    forwardPath = "/customer2/updatecustomer.jsp";
                    //3.将customer放入request中
                    req.setAttribute("customer", customer);
                }
            } catch (Exception e) {
                LOGGER.info("edit customer error", e);
            }
        }
        //4.响应updatecustomer.jsp页面：转发
        req.getRequestDispatcher(forwardPath).forward(req, resp);
    }
}
